/**
 * Copyright &copy; 2012-2017 <a href="http://www.haohanwork.com">haohan</a> All rights reserved
 */
package com.haohan.cloud.scm.common.tools.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * 日期工具类, 继承org.apache.commons.lang.time.DateUtils类
 *
 * @author ThinkGem
 * @version 2014-4-15
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

  private static String[] parsePatterns = {
    "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
    "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
    "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM",
    "YYYYMMDDHHmmss"};

  /**
   * 得到当前日期字符串 格式（yyyy-MM-dd）
   */
  public static String getDate() {
    return getDate("yyyy-MM-dd");
  }

  /**
   * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
   */
  public static String getDate(String pattern) {
    return DateFormatUtils.format(new Date(), pattern);
  }

  /**
   * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
   */
  public static String formatDate(Date date, Object... pattern) {
    String formatDate = null;
    if (null == date) {
      return formatDate;
    }
    if (pattern != null && pattern.length > 0) {
      formatDate = DateFormatUtils.format(date, pattern[0].toString());
    } else {
      formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
    }
    return formatDate;
  }

  /**
   * 得到日期时间字符串，转换格式（yyyy-MM-dd HH:mm:ss）
   */
  public static String formatDateTime(Date date) {
    return formatDate(date, "yyyy-MM-dd HH:mm:ss");
  }


  public static String getWsTime() {

    return formatDate(new Date(), "yyyyMMddHHmmss");
  }


  /**
   * 得到当前时间字符串 格式（HH:mm:ss）
   */
  public static String getTime() {
    return formatDate(new Date(), "HH:mm:ss");
  }

  /**
   * 得到当前日期和时间字符串 格式（yyyy-MM-dd HH:mm:ss）
   */
  public static String getDateTime() {
    return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
  }

  /**
   * 得到当前年份字符串 格式（yyyy）
   */
  public static String getYear() {
    return formatDate(new Date(), "yyyy");
  }

  /**
   * 得到当前月份字符串 格式（MM）
   */
  public static String getMonth() {
    return formatDate(new Date(), "MM");
  }

  /**
   * 得到当天字符串 格式（dd）
   */
  public static String getDay() {
    return formatDate(new Date(), "dd");
  }

  /**
   * 得到当前星期字符串 格式（E）星期几
   */
  public static String getWeek() {
    return formatDate(new Date(), "E");
  }

  /**
   * 日期型字符串转化为日期 格式
   * { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
   * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",
   * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm" }
   */
  public static Date parseDate(Object str) {
    if (str == null) {
      return null;
    }
    try {
      return parseDate(str.toString(), parsePatterns);
    } catch (ParseException e) {
      return null;
    }
  }

  /**
   * 获取过去的天数
   *
   * @param date
   * @return
   */
  public static long pastDays(Date date) {
    long t = System.currentTimeMillis() - date.getTime();
    return t / (24 * 60 * 60 * 1000);
  }

  /**
   * 获取过去的小时
   *
   * @param date
   * @return
   */
  public static long pastHour(Date date) {
    long t = System.currentTimeMillis() - date.getTime();
    return t / (60 * 60 * 1000);
  }

  /**
   * 获取过去的分钟
   *
   * @param date
   * @return
   */
  public static long pastMinutes(Date date) {
    long t = System.currentTimeMillis() - date.getTime();
    return t / (60 * 1000);
  }

  /**
   * 转换为时间（天,时:分:秒.毫秒）
   *
   * @param timeMillis
   * @return
   */
  public static String formatDateTime(long timeMillis) {
    long day = timeMillis / (24 * 60 * 60 * 1000);
    long hour = (timeMillis / (60 * 60 * 1000) - day * 24);
    long min = ((timeMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
    long s = (timeMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
    long sss = (timeMillis - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000 - min * 60 * 1000 - s * 1000);
    return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + s + "." + sss;
  }

  /**
   * 获取两个日期之间的天数
   *
   * @param before
   * @param after
   * @return
   */
  public static double getDistanceOfTwoDate(Date before, Date after) {
    long beforeTime = before.getTime();
    long afterTime = after.getTime();
    return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
  }

  /**
   * 获取年对应的季度
   * ex: 2018-Q1
   *
   * @param date
   * @return
   */
  public static String getYearSeason(Date date) {
    return formatDate(date, "yyyy").concat("-Q").concat(getSeason(date) + "");
  }

  /**
   * 当前第几季度
   *
   * @param date
   * @return
   */
  public static int getSeason(Date date) {

    int season = 0;

    Calendar c = Calendar.getInstance();
    c.setTime(date);
    int month = c.get(Calendar.MONTH);
    switch (month) {
      case Calendar.JANUARY:
      case Calendar.FEBRUARY:
      case Calendar.MARCH:
        season = 1;
        break;
      case Calendar.APRIL:
      case Calendar.MAY:
      case Calendar.JUNE:
        season = 2;
        break;
      case Calendar.JULY:
      case Calendar.AUGUST:
      case Calendar.SEPTEMBER:
        season = 3;
        break;
      case Calendar.OCTOBER:
      case Calendar.NOVEMBER:
      case Calendar.DECEMBER:
        season = 4;
        break;
      default:
        break;
    }
    return season;
  }

  /**
   * @param args
   * @throws ParseException
   */
  public static void main(String[] args) throws ParseException {
//		System.out.println(formatDate(parseDate("2010/3/6")));
//		System.out.println(getDate("yyyy年MM月dd日 E"));
//		long time = new Date().getTime()-parseDate("2012-11-19").getTime();
//		System.out.println(time/(24*60*60*1000));
  }

  public static Long getUnixTime() {

    return System.currentTimeMillis() / 1000;
  }


  /**
   * 获取前一天0点时间
   *
   * @param date
   * @return
   */
  public static Date getStartOfYesterday(Date date) {
    long zero = System.currentTimeMillis() / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
    zero = zero - 1000 * 3600 * 24;
    return new Date(zero);
  }

  /**
   * 获取前一天23:59
   *
   * @param date
   * @return
   */
  public static Date getEndOfYesterday(Date date) {
    long zero = getStartOfYesterday(new Date()).getTime();
    return new Date(zero + 1000 * 3600 * 24 - 1);
  }

  /**
   * 获取当天零点
   *
   * @param date
   * @return
   */
  public static Date getStartOfToday(Date date) {
    return getDayStartTime(new Date());
  }

  /**
   * 获取本周一0点时间
   *
   * @return
   */
  public static Date getTimesWeekStart() {
    Calendar cal = Calendar.getInstance();
    cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
    cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    return cal.getTime();
  }

  /**
   * 获取本周日23:59点时间
   *
   * @return
   */
  public static Date getTimesWeekEnd() {
    Calendar cal = Calendar.getInstance();
    cal.setTime(getTimesWeekStart());
    cal.add(Calendar.DAY_OF_WEEK, 7);
    cal.add(Calendar.SECOND, -1);
    return cal.getTime();
  }

  /**
   * yyyyMMddHHmmss格式转换成Date
   *
   * @param datetime
   * @return
   */
  public static Date parseDateTime(String datetime) {
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    LocalDateTime localDateTime = LocalDateTime.parse(datetime, dateTimeFormatter);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    return parseDate(localDateTime.format(formatter));
  }

  /**
   * 获取n天后/前的日期
   *
   * @param date
   * @param offset
   * @return
   */
  public static Date getOffsetDate(Date date, int offset) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(calendar.DATE, offset);
    date = calendar.getTime();
    return date;
  }

  /**
   * 判断日期为周几
   *
   * @param date
   * @return
   */
  public static int getDayForWeek(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    int dayForWeek = 0;
    if (calendar.get(Calendar.DAY_OF_WEEK) == 1) {
      dayForWeek = 7;
    } else {
      dayForWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
    }
    return dayForWeek;
  }

  /**
   * 获取某天开始
   *
   * @param d
   * @return
   */
  public static Timestamp getDayStartTime(Date d) {
    Calendar calendar = Calendar.getInstance();
    if (null != d) {
      calendar.setTime(d);
    }
    calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
      calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return new Timestamp(calendar.getTimeInMillis());
  }

  /**
   * 获取某天结束
   *
   * @return
   */
  public static Timestamp getDayEndTime(Date d) {
    Calendar calendar = Calendar.getInstance();
    if (null != d) {
      calendar.setTime(d);
    }
      calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
        calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
      calendar.set(Calendar.MILLISECOND, 999);
      return new Timestamp(calendar.getTimeInMillis());
  }

  /**
   * 获取本月开始时间
   *
   * @return
   */
  public static Date getBeginDayOfMonth() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Integer.valueOf(getYear()), Integer.valueOf(getMonth()) - 1, 1);
    return getDayStartTime(calendar.getTime());
  }

  /**
   * 获取本月结束时间
   *
   * @return
   */
  public static Date getEndDayOfMonth() {
    Integer thisYear = Integer.valueOf(getYear());
    Integer thisMonth = Integer.valueOf(getMonth());
    Calendar calendar = Calendar.getInstance();
    calendar.set(thisYear, thisMonth - 1, 1);
    int day = calendar.getActualMaximum(5);
    calendar.set(Integer.valueOf(getYear()), Integer.valueOf(getMonth()) - 1, day);
    return getDayEndTime(calendar.getTime());
  }

  /**
   * 获取小时数
   *
   * @return
   */
  public static int getHourOnDay() {
    Calendar c = Calendar.getInstance();
    return c.get(Calendar.HOUR_OF_DAY);
  }

  public static Date getAnyTime(String yearStr, String monthStr, String dayStr, int hour, int minute, int second) {
    Calendar calendar = Calendar.getInstance();
    if (StringUtils.isNotBlank(yearStr)) {
      int year = Integer.parseInt(yearStr);
      calendar.set(Calendar.YEAR, year);
    } else if (StringUtils.isNotBlank(monthStr)) {
      int month = Integer.parseInt(monthStr);
      calendar.set(Calendar.MONTH, month - 1);
    } else if (StringUtils.isNotBlank(dayStr)) {
      int day = Integer.parseInt(dayStr);
      calendar.set(Calendar.DAY_OF_MONTH, day);
    }

    calendar.set(Calendar.HOUR_OF_DAY, hour);
    calendar.set(Calendar.MINUTE, minute);
    calendar.set(Calendar.SECOND, second);

    Date date = calendar.getTime();
    return date;
  }


  public static Date transTimeToDate(Date date) {
    String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd");
    return parseDate(dateStr);
  }

}
